/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.web.appconfig.core.service;

import com.inspur.edp.lcm.metadata.api.entity.MetadataProject;
import com.inspur.edp.lcm.metadata.api.service.MetadataProjectService;
import com.inspur.edp.web.appconfig.api.entity.GspAppConfig;
import com.inspur.edp.web.appconfig.core.appconfig.AppConfigFileManager;
import com.inspur.edp.web.appconfig.core.appconfig.AppConfigFilePathGenerator;
import com.inspur.edp.web.common.customexception.WebCustomException;
import com.inspur.edp.web.common.entity.TerminalType;
import com.inspur.edp.web.common.io.FileUtility;
import com.inspur.edp.web.common.metadata.GspProjectUtility;
import com.inspur.edp.web.common.metadata.MetadataUtility;
import com.inspur.edp.web.common.serialize.SerializeUtility;
import com.inspur.edp.web.common.utility.StringUtility;
import io.iec.edp.caf.commons.exception.CAFRuntimeException;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;

/**
 * app.config文件对外服务
 *
 * @author noah
 */
public class GspAppConfigService {
    private static final GspAppConfigService current = new GspAppConfigService();

    private GspAppConfigService() {
    }

    public static GspAppConfigService getCurrent() {
        return current;
    }

    /**
     * 基于相对路径（不包含开发路径），获取app.config文件内容
     *
     * @param relativeProjectPath
     * @return
     */
    public final GspAppConfig getGspAppConfigInfo(String relativeProjectPath) {
        if (StringUtility.isNullOrEmpty(relativeProjectPath)) {
            return null;
        }
        String appConfigFolderPath = combinePathWithDevRootPath(relativeProjectPath);
        String appConfigFilePath = AppConfigFilePathGenerator.generateAppConfigFilePath(appConfigFolderPath);
        return AppConfigFileManager.getAppConfigWithPath(appConfigFilePath);
    }

    /**
     * 获取或新建app.config.json 文件及其内容
     *
     * @param projectPath 工程路径
     * @return 应用实体
     */
    public GspAppConfig getOrCreateAppConfig(String projectPath) {
        GspAppConfig gspAppConfig = getGspAppConfigInfo(projectPath);
        if (gspAppConfig == null) {
            gspAppConfig = createEmptyAppConfigFile(projectPath);
        }
        return gspAppConfig;
    }

    /**
     * 创建app.config.json 空文件
     * 如果app.config.json 文件不存在 那么创建对应的文件
     *
     * @param appConfigFileFolderPath 工程路径 scm/sd/..../bo-
     */
    private GspAppConfig createEmptyAppConfigFile(String appConfigFileFolderPath) {
        return AppConfigFileManager.createEmptyAppConfigFile(appConfigFileFolderPath);
    }

    /**
     * 获取开发元数据绝对路径 将当前路径和devRootPath合并
     *
     * @param path
     * @return
     */
    private String combinePathWithDevRootPath(String path) {
        //开发根路径
        String devRootPath = MetadataUtility.getInstance().getDevRootPath();
        return FileUtility.getPlatformIndependentPath(FileUtility.combine(devRootPath, path));
    }

    /**
     * 根据元数据信息，更新工程下的app.config.json文件中内容
     */
    public final void updateAppConfigFileWhenPageFlowFileCreated(String pageFlowMetadataID, String pageFlowMetadataFileName, String pageFlowMetadataFullPath) {
        TerminalType terminalType = TerminalType.PC;
        if (pageFlowMetadataFileName.endsWith("mpf")) {
            terminalType = TerminalType.MOBILE;
        }
        updateAppConfigFile(terminalType, pageFlowMetadataID, pageFlowMetadataFileName, pageFlowMetadataFullPath);
    }

    /**
     * 根据元数据信息，更新工程下的app.config.json文件中内容
     */
    public final void updateAppConfigFile(TerminalType terminalType, String pageFlowMetadataID, String pageFlowMetadataFileName, String pageFlowMetadataFullPath) {
        String appConfigPath = getAppConfigPath(pageFlowMetadataFullPath);
        String appConfigContent = FileUtility.readAsString(appConfigPath);
        GspAppConfig appConfig = SerializeUtility.getInstance().deserialize(appConfigContent, GspAppConfig.class);
        switch (terminalType) {
            case PC:
                appConfig.setPageFlowMetadataID(pageFlowMetadataID);
                appConfig.setPageFlowMetadataFileName(pageFlowMetadataFileName);
                appConfig.setPageFlowMetadataPath(pageFlowMetadataFullPath);
                break;
            case MOBILE:
                appConfig.setMobilePageFlowMetadataID(pageFlowMetadataID);
                appConfig.setMobilePageFlowMetadataFileName(pageFlowMetadataFileName);
                appConfig.setMobilePageFlowMetadataPath(pageFlowMetadataFullPath);
                break;
            default:
                throw new WebCustomException("未识别的终端类型，请联系管理员处理。当前终端类型是：" + terminalType);
        }

        modifyPageFlowMetadataPath(appConfig, pageFlowMetadataFullPath);
        AppConfigFileManager.saveAppConfig(appConfigPath, appConfig);
    }


    /**
     * 保存app.config.json文件内容
     *
     * @param projectPath     app.config.json所在工程路径
     * @param appConfigEntity 待保存appConfig Entity
     */
    public final void saveAppConfigFile(String projectPath, GspAppConfig appConfigEntity) {
        // 获取app.config.json文件路径
        String appConfigPath = getAppConfigPath(projectPath);
        // 调整页面流中路径为基于工程相对路径
        modifyPageFlowMetadataPath(appConfigEntity, projectPath);

        AppConfigFileManager.saveAppConfig(appConfigPath, appConfigEntity);
    }

    /**
     * 调整页面流路径为基于工程名称相对路径
     *
     * @param appConfigEntity config 应用实体
     * @param projectPath     工程路径
     */
    private void modifyPageFlowMetadataPath(GspAppConfig appConfigEntity, String projectPath) {
        if (appConfigEntity == null) {
            return;
        }
        String projectName = GspProjectUtility.getProjectName(projectPath);
        // 如果pc页面流路径不为空
        if (!StringUtility.isNullOrEmpty(appConfigEntity.getPageFlowMetadataPath())) {
            String relativePageFlowMetadataPath = getRelativePageflowMetadataPath(appConfigEntity.getPageFlowMetadataPath(), projectName);
            appConfigEntity.setPageFlowMetadataPath(relativePageFlowMetadataPath);
        }
        // 如果pc页面流路径不为空
        if (!StringUtility.isNullOrEmpty(appConfigEntity.getMobilePageFlowMetadataPath())) {
            String relativeMobilePageFlowMetadataPath = getRelativePageflowMetadataPath(appConfigEntity.getMobilePageFlowMetadataPath(), projectName);
            appConfigEntity.setMobilePageFlowMetadataPath(relativeMobilePageFlowMetadataPath);
        }
    }

    /**
     * 获取页面流相对于工程的相对路径
     *
     * @param pageFlowMetadataPath
     * @param projectName
     * @return
     */
    private String getRelativePageflowMetadataPath(String pageFlowMetadataPath, String projectName) {
        String independentPageFlowMetadataPath = FileUtility.getPlatformIndependentPath(pageFlowMetadataPath);
        // 表示当前页面流中包含工程名称
        if (independentPageFlowMetadataPath.contains(projectName)) {
            independentPageFlowMetadataPath = independentPageFlowMetadataPath.substring(independentPageFlowMetadataPath.indexOf(projectName) + projectName.length());
            if (independentPageFlowMetadataPath.startsWith("/")) {
                independentPageFlowMetadataPath = independentPageFlowMetadataPath.substring(1);
            }
        }
        return independentPageFlowMetadataPath;
    }

    private String getAppConfigPath(String metadataFullPath) {
        // 基于当前元数据获取工程路径信息
        String projectPath = getMetadataProjectPath(metadataFullPath);
        // 获取app.config.json文件内容
        return AppConfigFilePathGenerator.generateAppConfigFilePath(projectPath);
    }

    /**
     * 获取当前元数据所在工程路径
     */
    private String getMetadataProjectPath(String metadataFullPath) {
        MetadataProjectService bean = SpringBeanUtils.getBean(MetadataProjectService.class);
        MetadataProject metadataProject = bean.getMetadataProjInfo(metadataFullPath);

        return getAbsPath(metadataProject.getProjectPath());
    }

    private String getAbsPath(String relPath) {
        String devRootPath = MetadataUtility.getInstance().getDevRootPath();
        if (relPath.contains(devRootPath)) {
            return relPath;
        }
        return java.nio.file.Paths.get(devRootPath).resolve(relPath).toString();
    }
}
